/**
 * 文件上传工具类
 * 处理图片等文件的上传、存储和访问路径生成
 */
const fs = require('fs');
const path = require('path');
const { v4: uuidv4 } = require('uuid');

class FileUploader {
  /**
   * 初始化文件上传器
   * @param {Object} options - 配置选项
   */
  constructor(options = {}) {
    // 上传目录，默认为uploads/images
    this.uploadDir = options.uploadDir || path.join(__dirname, '../uploads/images');
    // 允许的图片MIME类型
    this.allowedMimeTypes = options.allowedMimeTypes || [
      'image/jpeg',
      'image/png',
      'image/gif',
      'image/webp'
    ];
    // 最大文件大小（字节），默认10MB
    this.maxFileSize = options.maxFileSize || 10 * 1024 * 1024;
    
    // 确保上传目录存在
    this.ensureUploadDirExists();
  }

  /**
   * 确保上传目录存在
   */
  ensureUploadDirExists() {
    if (!fs.existsSync(this.uploadDir)) {
      fs.mkdirSync(this.uploadDir, { recursive: true });
    }
  }

  /**
   * 验证文件是否有效
   * @param {Object} file - 文件对象
   * @returns {Object} 验证结果 { valid: boolean, error: string }
   */
  validateFile(file) {
    // 检查文件大小
    if (file.size > this.maxFileSize) {
      return {
        valid: false,
        error: `文件大小超过限制，最大允许${this.maxFileSize / (1024 * 1024)}MB`
      };
    }

    // 检查文件类型
    if (!this.allowedMimeTypes.includes(file.mimetype)) {
      return {
        valid: false,
        error: '不支持的文件类型，仅允许JPG、PNG、GIF、WebP格式'
      };
    }

    return { valid: true, error: null };
  }

  /**
   * 从Data URL保存图片
   * @param {string} dataUrl - Base64编码的图片数据URL
   * @param {string} prefix - 文件名前缀
   * @returns {Promise<string>} 保存的文件相对路径
   */
  async saveImageFromDataUrl(dataUrl, prefix = 'image') {
    try {
      // 解析data URL
      const matches = dataUrl.match(/^data:(.+);base64,(.+)$/);
      if (!matches || matches.length !== 3) {
        throw new Error('无效的图片数据格式');
      }

      const mimeType = matches[1];
      const base64Data = matches[2];

      // 检查MIME类型
      if (!this.allowedMimeTypes.includes(mimeType)) {
        throw new Error('不支持的图片类型');
      }

      // 获取文件扩展名
      const extension = mimeType.split('/')[1];

      // 生成唯一文件名
      const filename = `${prefix}_${uuidv4()}.${extension}`;
      const filePath = path.join(this.uploadDir, filename);
      
      // 解码Base64并写入文件
      const buffer = Buffer.from(base64Data, 'base64');
      fs.writeFileSync(filePath, buffer);

      // 返回相对路径
      return `/uploads/images/${filename}`;
    } catch (error) {
      console.error('保存图片失败:', error);
      throw error;
    }
  }

  /**
   * 批量保存多张图片
   * @param {Array<string>} dataUrls - Base64编码的图片数据URL数组
   * @param {string} prefix - 文件名前缀
   * @returns {Promise<Array<string>>} 保存的文件相对路径数组
   */
  async saveMultipleImages(dataUrls, prefix = 'image') {
    if (!Array.isArray(dataUrls) || dataUrls.length === 0) {
      return [];
    }

    const savePromises = dataUrls.map((dataUrl, index) => 
      this.saveImageFromDataUrl(dataUrl, `${prefix}_${index}`)
    );

    return Promise.all(savePromises);
  }

  /**
   * 删除文件
   * @param {string} filePath - 文件相对路径
   * @returns {boolean} 删除结果
   */
  deleteFile(filePath) {
    try {
      // 转换为绝对路径
      const absolutePath = path.join(__dirname, '../uploads', filePath.replace('/uploads/', ''));
      
      if (fs.existsSync(absolutePath)) {
        fs.unlinkSync(absolutePath);
        return true;
      }
      return false;
    } catch (error) {
      console.error('删除文件失败:', error);
      return false;
    }
  }

  /**
   * 批量删除文件
   * @param {Array<string>} filePaths - 文件相对路径数组
   * @returns {Array<boolean>} 删除结果数组
   */
  deleteMultipleFiles(filePaths) {
    if (!Array.isArray(filePaths) || filePaths.length === 0) {
      return [];
    }

    return filePaths.map(filePath => this.deleteFile(filePath));
  }

  /**
   * 获取文件的完整URL
   * @param {string} relativePath - 文件相对路径
   * @param {string} baseUrl - 基础URL
   * @returns {string} 完整的文件URL
   */
  getFileUrl(relativePath, baseUrl = '') {
    if (!relativePath) return '';
    // 如果已经是完整URL，直接返回
    if (relativePath.startsWith('http://') || relativePath.startsWith('https://')) {
      return relativePath;
    }
    return `${baseUrl}${relativePath}`;
  }
}

module.exports = new FileUploader();